import numpy as np
import math

a = np.array ([9, 8, 7, 6, 5, ])

# 带参数检查的单一函数返回值参数
def my_abs(x):
    if not isinstance(x, (int, float)):
        raise TypeError("bac operand type")       # 参数错误时，向外抛出异常
    if x >= 0:
        return x
    else:
        return -x;

# 返回多个值的函数（本质是返回tuple类型）
def move(x, y, step, angle = 0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny

# 带默认参数的函数
def enroll(name, gender, age = 6, city = "Beijing"):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)

# 注意: Python 在函数定义时，默认参数的值已经完成计算，每次调用如果改变默认参数的值，则下次调用时，默认参数的内容就变了！
# 示例（错误的）:
def add_end_func1(L = []):
    L.append('END')
    return L

# 改用不变对象重写 add_end_func1
def add_end_func2(L = None):
    if L is None:
        L = []
    L.append('END')
    return L

# 可变参数（允许传入0个或任意个参数，调用时自动组装为tuple）
def calc_square_sum(*number):
    sum = 0
    for n in number:
        sum = sum + n * n
    return sum

# 关键字参数（允许传入0个或任意个含参数名的参数，调用时自动组装为dict）
def person_func1(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

# 命名关键字参数（特殊分隔符'*'限制关键字参数类型），如果函数定义中已经有了一个可变参数，后面跟着的命名关键字参数就不再需要一个特殊分隔符
# 此外，命名关键字必须传入参数名
def person_func2(name, age, *, city, job):
    print(name, age, city, job)

def person_func3(name, age, *args, city, job):
    print(name, age, args, city, job)

# 以下为上述相关函数的调用过程
print(move(100, 100, 60, math.pi / 6))
print(my_abs(-5))

enroll('Ben', 'F', city = "Shanghai")

print(add_end_func1())
print(add_end_func1())

print(add_end_func2())
print(add_end_func2())

print(calc_square_sum(1, 2, 3))
print(calc_square_sum(*[1, 2, 3]))

person_func1('Adam', 45, gender = 'M', job = 'Engineer')